home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Sound / Amster / Source / thread.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-14  |  5.5 KB  |  321 lines

  1. /*
  2. ** Amster - Threading functions
  3. ** Copyright © 1999-2000 by Gürer Özen
  4. **
  5. ** This program is free software; you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation; either version 2 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. */
  19.  
  20. #include "amster.h"
  21.  
  22. #include <stdlib.h>
  23. #include <string.h>
  24.  
  25. #include <proto/exec.h>
  26. #include <proto/dos.h>
  27. #include <dos/dostags.h>
  28.  
  29. #include "thread.h"
  30.  
  31. struct MsgPort *th_mother=NULL;
  32. thread th_list=NULL;
  33. u_long th_sigmask=0;
  34.  
  35. void th_handlemsg(thmsg m);
  36. void th_cleanup(thread t);
  37.  
  38.  
  39. int th_init(void)
  40. {
  41.     th_mother = CreateMsgPort();
  42.     if (!th_mother) return(0);
  43.     th_sigmask = 1L << (th_mother->mp_SigBit);
  44.     return(1);
  45. }
  46.  
  47.  
  48. void th_exit(void)
  49. {
  50.     thread t;
  51.  
  52.     t = th_list;
  53.     while (t) {
  54.         th_message(t, THC_EXIT, 0);
  55.         t = t->next;
  56.     }
  57.  
  58.     while (th_list) {
  59.         thmsg m;
  60.         WaitPort(th_mother);
  61.         m = (thmsg)GetMsg(th_mother);
  62.         th_handlemsg(m);
  63.     }
  64.  
  65.     DeleteMsgPort(th_mother);
  66.     th_sigmask = 0;
  67. }
  68.  
  69.  
  70. thread th_spawn(thcb handler, char *name, void (*func)(void), int pri, APTR data)
  71. {
  72.     thread t;
  73.  
  74.     t = malloc(sizeof(_thread));
  75.     if (!t) return(NULL);
  76.     memset(t, 0, sizeof(_thread));
  77.  
  78.     t->task = (struct Task *)CreateNewProcTags(
  79.         NP_Entry, func,
  80.         NP_Name, name,
  81.         NP_StackSize, 16384,
  82.         NP_Priority, pri,
  83.         TAG_DONE);
  84.  
  85.     if (!t->task) {
  86.         free(t);
  87.         return(NULL);
  88.     }
  89.  
  90.     t->handler = handler;
  91.     t->mother = th_mother;
  92.     t->data = data;
  93.  
  94.     t->sm.header.mn_ReplyPort = th_mother;
  95.     t->sm.header.mn_Length = sizeof(_thmsg);
  96.     t->sm.com = THC_STARTUP;
  97.     t->sm.data = t;
  98.  
  99.     /* Begin new stuff */
  100.     t->task->tc_UserData = &t->sm;
  101.     t->mother_task = FindTask(NULL);
  102.     SetSignal(0L, SIGF_SINGLE);
  103.     Signal(t->task, SIGF_SINGLE);
  104.     Wait(SIGF_SINGLE);
  105.     /* End new stuff */
  106.  
  107.     /* Old stuff
  108.     PutMsg(&((struct Process *)t->task)->pr_MsgPort,(struct Message *)&t->sm);
  109.        End old stuff */
  110.  
  111.     /* Begin new stuff */
  112.     if (handler)    (handler)(t, THC_STARTUP, data);
  113.     /* End new stuff */
  114.  
  115.     t->next = th_list;
  116.     th_list = t;
  117.     return(t);
  118. }
  119.  
  120.  
  121. void th_message(thread t, int com, APTR data)
  122. {
  123.     thmsg m;
  124.  
  125. #ifdef AMSTER_DEBUG
  126. gui_debug("th_message 1");
  127. #endif
  128.     if (!t) return;
  129. #ifdef AMSTER_DEBUG
  130. gui_debug("th_message 2");
  131. #endif
  132.     if (!t->port) return;
  133. #ifdef AMSTER_DEBUG
  134. gui_debug("th_message 3");
  135. #endif
  136.  
  137.     m = malloc(sizeof(_thmsg));
  138.     if (!m) return;
  139.     memset(m,0,sizeof(_thmsg));
  140.  
  141. #ifdef AMSTER_DEBUG
  142. gui_debug("th_message 4");
  143. #endif
  144.     m->header.mn_ReplyPort = th_mother;
  145.     m->header.mn_Length = sizeof(_thmsg);
  146.     m->com = com;
  147.     m->data = data;
  148.  
  149. #ifdef AMSTER_DEBUG
  150. gui_debug("th_message 5");
  151. #endif
  152.     PutMsg(t->port,(struct Message *)m);
  153. }
  154.  
  155.  
  156. void th_poll(void)
  157. {
  158.     thread t;
  159.     thmsg m;
  160.  
  161.     while(1) {
  162.         m = (thmsg)GetMsg(th_mother);
  163.         if(!m) break;
  164.  
  165.         if(m->com != THC_FINISH && (!m->isreply)) {
  166.             t = m->sender;
  167.             if(t && t->handler)
  168.                 (t->handler)(t,m->com,m->data);
  169.         }
  170.  
  171.         th_handlemsg(m);
  172.     }
  173. }
  174.  
  175.  
  176. thread thr_init(void)
  177. {
  178.     thread t;
  179.     thmsg m;
  180.     struct Task *me = FindTask(NULL);
  181.  
  182.     /* Begin new stuff */
  183.     Wait(SIGF_SINGLE);
  184.     m = (thmsg)me->tc_UserData;
  185.     t = (thread)m->data;
  186.  
  187.     t->port = CreateMsgPort();
  188.     if (!t->port) {
  189.         me->tc_UserData = (APTR)FALSE;
  190.         t = NULL;
  191.     }
  192.     else {
  193.         me->tc_UserData = (APTR)TRUE;
  194.         m->sender = t;
  195.     }
  196.     Signal(t->mother_task, SIGF_SINGLE);
  197.     /* End new stuff */
  198.  
  199.     /* Begin old stuff
  200.     WaitPort(&((struct Process *)me)->pr_MsgPort);
  201.     m = (thmsg)GetMsg(&((struct Process *)me)->pr_MsgPort);
  202.     t = m->data;
  203.  
  204.     t->port = CreateMsgPort();
  205.     if (!t->port) return(NULL);
  206.  
  207.     m->sender = t;
  208.     ReplyMsg((struct Message *)m);
  209.        End old stuff */
  210.  
  211.     return(t);
  212. }
  213.  
  214.  
  215. void thr_exit(thread t, int reason)
  216. /* Inside the thread */
  217. {
  218.     thmsg m=NULL;
  219.     BOOL waiting = TRUE;
  220.  
  221.     t->em.header.mn_ReplyPort = t->port;
  222.     t->em.header.mn_Length = sizeof(_thmsg);
  223.     t->em.com = THC_EXIT;
  224.     t->em.data = (APTR)reason;
  225.     t->em.sender = t;
  226.     PutMsg(t->mother, (struct Message *)&t->em);
  227.  
  228.     while (waiting) {
  229.         WaitPort(t->port);
  230.         while(m = (thmsg)GetMsg(t->port))
  231.         {
  232.             if (&t->em == m) {
  233.                 /*
  234.                 if(m->header.mn_ReplyPort != t->port)
  235.                 {
  236.                     ReplyMsg((struct Message *)m);
  237.                 }
  238.                 */
  239.                 waiting = FALSE;
  240.             }
  241.             m->isreply = 1;
  242.             /*
  243.             if(m->header.mn_ReplyPort != t->port)
  244.             {
  245.                 ReplyMsg((struct Message *)m);
  246.             }
  247.             */
  248.         }
  249.     }
  250.  
  251.     t->em.header.mn_ReplyPort = NULL;
  252.     t->em.sender = t;
  253.     t->em.com = THC_FINISH;
  254.     PutMsg(t->mother, (struct Message *)&t->em);
  255.  
  256.     if (t->port)
  257.     {
  258.         Forbid();
  259.         DeleteMsgPort(t->port);
  260.         Permit();
  261.     }
  262. }
  263.  
  264.  
  265. void thr_message(thread t, int com, APTR data)
  266. {
  267.     thmsg m;
  268.  
  269.     m = malloc(sizeof(_thmsg));
  270.     if (!m) return;
  271.     memset(m, 0, sizeof(_thmsg));
  272.  
  273.     m->header.mn_ReplyPort = t->port;
  274.     m->header.mn_Length = sizeof(_thmsg);
  275.     m->sender = t;
  276.     m->com = com;
  277.     m->data = data;
  278.  
  279.     PutMsg(t->mother, (struct Message *)m);
  280. }
  281.  
  282.  
  283. /* private functions */
  284.  
  285. void th_handlemsg(thmsg m)
  286. {
  287.     if (m->com == THC_STARTUP) return;
  288.  
  289.     if (m->com == THC_FINISH) {
  290.         th_cleanup(m->sender);
  291.     }
  292.     else {
  293.         if (m->isreply) {
  294.             free(m);
  295.         }
  296.         else {
  297.             m->isreply = 1;
  298.             ReplyMsg((struct Message *)m);
  299.         }
  300.     }
  301. }
  302.  
  303.  
  304. void th_cleanup(thread t)
  305. {
  306.     if (th_list==t) {
  307.         th_list = t->next;
  308.     }
  309.     else {
  310.         thread tmp = th_list;
  311.         while (tmp) {
  312.             if (tmp->next==t) {
  313.                 tmp->next=t->next;
  314.                 break;
  315.             }
  316.             tmp = tmp->next;
  317.         }
  318.     }
  319.     free(t);
  320. }
  321.